Skip to content

feat: audit fixes — graceful OTEL, async-safe plugins, URL validation, +100 tests#36

Merged
haasonsaas merged 8 commits intomainfrom
feat/audit-fixes
Mar 11, 2026
Merged

feat: audit fixes — graceful OTEL, async-safe plugins, URL validation, +100 tests#36
haasonsaas merged 8 commits intomainfrom
feat/audit-fixes

Conversation

@haasonsaas
Copy link
Collaborator

@haasonsaas haasonsaas commented Mar 11, 2026

Summary

  • Graceful OTEL degradation: init_otel() no longer panics on misconfigured endpoints — logs a warning and continues without tracing
  • Async-safe plugin execution: Semgrep and ESLint analyzers now use tokio::task::spawn_blocking to avoid blocking the async runtime; semgrep gets a 30s --timeout flag
  • URL validation for pattern repos: prepare_pattern_repository_checkout() now rejects non-https/git@ URLs via is_safe_git_url(), preventing command injection through malicious repo sources
  • PartialEq on ContextType: Enables direct equality assertions in tests
  • 100+ new tests: Comprehensive coverage for JSON storage backend, interactive command parsing, plugin analyzers (semgrep, eslint, duplicate_filter), CLI commands (pr.rs, git.rs)

Test plan

  • cargo test — 970 tests passing
  • cargo clippy — clean
  • cargo fmt --check — clean
  • CI passes all checks

🤖 Generated with Claude Code


Open with Devin

…, +100 tests

- OTEL init no longer panics on misconfigured endpoints; falls back gracefully
- Semgrep/ESLint plugins use tokio::spawn_blocking to avoid blocking the runtime
- Added semgrep --timeout flag (30s) for process execution safety
- Git clone URL validation: only https://, git@, and http://*.git accepted
- Added PartialEq derive to ContextType for test assertions
- 100+ new tests across storage_json, interactive commands, plugins,
  CLI commands (pr.rs, git.rs), and duplicate_filter

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 5 additional findings.

Open in Devin Review

…dedup severity, empty LLM responses

Bug 1: `is_comment_line` missed bare `#` (shell/Makefile/Python comments)
  - Changed `#!` → `#![` in non-comment prefixes (Rust inner attrs always have `[`)
  - Any `#` line not matching a known code prefix is now treated as a comment

Bug 2: `find_function_end` ignored single-quoted strings
  - `'{'` in JS/Python strings was counted as a real brace, breaking function
    boundary detection. Now tracks both `"` and `'` string delimiters.

Bug 3: `deduplicate_comments` could drop higher-severity comments
  - `dedup_by` keeps the first element; sort didn't include severity.
    Now sorts by severity (highest first) within same file/line/content group.

Bug 4: OpenAI/Anthropic silently returned empty string for empty responses
  - Empty `choices`/`content` arrays now return errors instead of succeeding
    with empty content, preventing silent failures in the review pipeline.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
devin-ai-integration[bot]

This comment was marked as resolved.

haasonsaas and others added 5 commits March 11, 2026 13:39
… file status

- Error rate now counts only explicit review.failed events, not all non-completed
- Empty lines in diffs treated as context instead of being silently skipped
- parse_text_diff sets is_new/is_deleted based on empty old/new content
- Default model changed from Sonnet to Opus per project conventions
- Added 5 new tests covering all discovered issues

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Skip single-quote tracking for Rust in find_function_end (lifetimes
  like 'a/'static are not string delimiters, were breaking brace count)
- Add #!/ to HASH_NON_COMMENT_PREFIXES so shebang lines are not
  misclassified as comments (changing interpreter is a real code change)
- Added 2 regression tests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…lean up comments

- Fix DeduplicateStage in composable_pipeline.rs to preserve highest
  severity when deduplicating (same bug as comment.rs, different path)
- Accept ssh:// URLs in is_safe_git_url (was rejecting legitimate SSH)
- Consolidate is_git_source to delegate to is_safe_git_url
- Replace stale "BUG:" test comments with "Regression:" phrasing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Wrap semgrep/eslint spawn_blocking in tokio::time::timeout to prevent
  hanging subprocesses from permanently consuming blocking pool threads
- Replace false-positive semgrep test (tested struct construction, not
  analyzer) with actual timeout behavior test
- Replace eslint extension test with direct JS_EXTENSIONS unit test
  that verifies filter membership rather than relying on end-to-end run
- Fix DeduplicateStage in composable_pipeline to preserve highest
  severity (same bug as comment.rs dedup, different code path)
- Accept ssh:// URLs in is_safe_git_url
- Clean up stale BUG: comments to Regression: phrasing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
devin-ai-integration[bot]

This comment was marked as resolved.

Both backends now count only explicit review.failed events as failures,
not all non-completed events. Fixes inconsistency where PG counted
timeouts as failures but JSON did not.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@haasonsaas haasonsaas merged commit 9d9bee8 into main Mar 11, 2026
6 checks passed
@haasonsaas haasonsaas deleted the feat/audit-fixes branch March 11, 2026 21:10
Copy link

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

View 16 additional findings in Devin Review.

Open in Devin Review

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 CLI --model default still uses claude-sonnet-4-6, overriding the config default change to Opus

The default_model() in src/config.rs:1064 was changed to "claude-opus-4-6" to comply with CLAUDE.md ("Use frontier models for reviews — never default to smaller models"). However, the CLI argument at src/main.rs:33 still has default_value = "claude-sonnet-4-6". Since main.rs:356 always calls config.merge_with_cli(Some(cli.model.clone()), ...) — and clap always provides a value when default_value is set — the CLI default of Sonnet will always override the config-level Opus default. This makes the default_model() change in this PR effectively dead code for all CLI users.

How the override chain works
  1. Config::load() deserializes with default_model()"claude-opus-4-6"
  2. merge_with_cli(Some("claude-sonnet-4-6"), ...) overwrites self.model unconditionally
  3. User gets Sonnet, not Opus, unless they explicitly pass --model

(Refers to line 33)

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant